package com.yazi.mxz.mobile.common;

import javax.annotation.Resource;

import org.apache.shiro.SecurityUtils;
import org.apache.shiro.session.InvalidSessionException;
import org.apache.shiro.session.Session;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import com.myframework.smhj.common.exception.MyException;
import com.myframework.smhj.common.tool.DateUtil;
import com.myframework.smhj.jackson.result.ObjectResult;
import com.myframework.smhj.jackson.result.StatusResult;
import com.yazi.mxz.common.ComSetting;
import com.yazi.mxz.common.MyUtil;
import com.yazi.mxz.common.entity.beans.Email;
import com.yazi.mxz.common.entity.beans.Sms;
import com.yazi.mxz.common.entity.enums.EmailType;
import com.yazi.mxz.common.entity.enums.SettingId;
import com.yazi.mxz.common.entity.enums.SmsType;
import com.yazi.mxz.common.service.EmailService;
import com.yazi.mxz.common.service.SmsService;


public abstract class VerifyAbstractController extends BaseController {
	private static Logger log = LoggerFactory.getLogger(VerifyAbstractController.class);
	/**
	 * 密码验证时间信息的Session key
	 */
	private static final String SESSION_KEY_PWD_VERIFIED_TIME = "pwdVerifiedTime";
	/**
	 * 短信验证码信息的Session key
	 */
	private static final String SESSION_KEY_SMS = "smsCaptcha";
	/**
	 * 邮件验证码信息的Session key
	 */
	private static final String SESSION_KEY_EMAIL = "emailCaptcha";
	
	@Resource
	SmsService smsService;
	@Resource
	EmailService emailService;
	
	
	@RequestMapping("/verifyPwdDo/json")
	@ResponseBody
	public StatusResult verifyPwdDoJson(String pwd) {
		log.debug("密码验证");
		StatusResult jsonResult = new StatusResult();
		try {
			
			if (!MyUtil.checkPwd(getMember(), pwd)) {
				jsonResult.setFailMessage("密码不正确");
				return jsonResult;
			}
			setVerified(true);
			jsonResult.setOk();
		} catch (Exception e) {
			log.error("密码验证异常：", e);
			jsonResult.setErrorMessage("操作失败");
		}
		return jsonResult;
	}
	
	@RequestMapping("/isPwdVerified/json")
	@ResponseBody
	public ObjectResult<Boolean> isPwdVerifiedJson() {
		ObjectResult<Boolean> jsonResult = new ObjectResult<Boolean>();
		jsonResult.setResult(isVerified());
		jsonResult.setOk();
		return jsonResult;
	}
	
	protected void removeSession(Object key) {
		getSession().removeAttribute(key);
	}
	
	protected Session getSession() {
		return SecurityUtils.getSubject().getSession();
	}
	
	/**
	 * 是否已经验证过密码<br>
	 * 绑定手机或者邮箱之前需要验证一次登录密码,以确认操作身份
	 * @return
	 */
	protected boolean isVerified() {
		Object obj= getSession().getAttribute(SESSION_KEY_PWD_VERIFIED_TIME);
		// TODO 身份验证有效性持续时间10分钟
		if (null == obj || (Long)obj < (DateUtil.getTimeStamp() - 6e5)) {
			return false;
		}
		return true;
	}
	
	/**
	 * 设定用户身份(身份验证)状态
	 */
	protected void setVerified(boolean bool) {
		if (bool) {
			getSession().setAttribute(SESSION_KEY_PWD_VERIFIED_TIME, DateUtil.getTimeStamp());
		} else {
			removeSession(SESSION_KEY_PWD_VERIFIED_TIME);
		}		
	}
	
	protected Captcha getSmsCaptcha() {
		return (Captcha)getSession().getAttribute(SESSION_KEY_SMS);
	}
	
	protected Captcha getEmailCaptcha() {
		return (Captcha) getSession().getAttribute(SESSION_KEY_EMAIL);
	}
	
	/**
	 * 手机和验证码校验
	 * @param mobile
	 * @param captcha
	 * @return
	 */
	protected boolean checkSmsCaptcha(String mobile, String captcha) {
		Captcha cap = getSmsCaptcha();
		// 没输入验证码、验证码不存在、手机号不一致或者超时
		if (null == captcha || null == cap || !mobile.equals(cap.getReceiver()) 
				|| (DateUtil.getTimeStamp() - cap.getTimestamp()) > ComSetting.getLong(SettingId.SMS_INDATE)) {
			return false;
		} 
		
		// 输入不正确
		if (!captcha.equals(cap.getCaptcha())) {
			cap.setFail(cap.getFail() + 1);
			getSession().setAttribute(SESSION_KEY_SMS, cap);
			return false;
		}
		
		// 正确后再删
		removeSession(SESSION_KEY_SMS);
		// 即使输入正确，但错误次数达到上限同样作为验证失败
		// 因为可能是无数次错误输入尝试后碰巧命中，这种情况下不予通过
		if (cap.getFail() >= ComSetting.getLong(SettingId.SMS_BRAKE)) {
			return false;
		}
		return true;
	}
	
	/**
	 * 邮箱和验证码校验
	 * @param mobile
	 * @param captcha
	 * @return
	 */
	protected boolean checkEmailCaptcha(String email, String captcha) {
		Captcha cap = getEmailCaptcha();
		if (null == captcha || null == cap || !email.equals(cap.getReceiver()) 
				|| (DateUtil.getTimeStamp() - cap.getTimestamp()) > ComSetting.getLong(SettingId.EMAIL_INDATE)) {
			return false;
		}
		
		// 输入不正确
		if (!captcha.equals(cap.getCaptcha())) {
			cap.setFail(cap.getFail() + 1);
			getSession().setAttribute(SESSION_KEY_EMAIL, cap);
			return false;
		}
		
		// 正确后再删
		removeSession(SESSION_KEY_EMAIL);
		// 即使输入正确，但错误次数达到上限同样作为验证失败
		if (cap.getFail() >= ComSetting.getLong(SettingId.EMAIL_BRAKE)) {
			return false;
		}
		
		return true;
	}
	
	protected void setCaptchaForMobile(String mobile) throws MyException {

		int captcha =  MyUtil.makeCaptcha();
		log.debug("发送验证码：mobile={}, 验证码={}", mobile, captcha);
		
		Captcha sc = new Captcha();
		sc.setCaptcha(captcha + "");
		sc.setReceiver(mobile);
		getSession().setAttribute(SESSION_KEY_SMS, sc);
		
		// 发短信
		Sms sms = new Sms();
		sms.setType(SmsType.BIND_ACCOUNT.ordinal());
		sms.setToMobile(mobile);
		// TODO 验证码|有效时间(单位：分钟)，格式固定
		sms.setParams(captcha + "|" + ComSetting.getLong(SettingId.SMS_INDATE)/60000);
		smsService.add(sms);
		
	}
	
	protected void setCaptchaForEmail(String memberName, String emailAddr) throws MyException, InvalidSessionException {
		int captcha =  MyUtil.makeCaptcha();
		log.debug("发送验证码：email={}, 验证码={}", emailAddr, captcha);
		Captcha ec = new Captcha();
		ec.setCaptcha(captcha + "");
		ec.setReceiver(emailAddr);
		getSession().setAttribute(SESSION_KEY_EMAIL, ec);
		
		// 发送邮件
		Email email = new Email();
		email.setType(EmailType.BIND_ACCOUNT.ordinal());
		email.setToEmail(emailAddr);
		// TODO 用户名|&|验证码|&|有效时间(单位：分钟)，格式固定
		email.setParams(memberName + "|&|" + captcha + "|&|" + ComSetting.getLong(SettingId.EMAIL_INDATE)/60000);
		emailService.add(email);
	}
	
	/**
	 * 短信发送时间间隔
	 * @return
	 */
	protected long getSmsLag() {
		return ComSetting.getLong(SettingId.SMS_LAG);
	}
	
	/**
	 * 邮件发送时间间隔
	 * @return
	 */
	protected long getEmailLag() {
		return ComSetting.getLong(SettingId.EMAIL_LAG);
	}
	
	protected class Captcha {
		// 目标手机号或者邮箱
		private String receiver;
		// 验证码
		private String captcha;
		// 验证码生成时间
		private long timestamp = DateUtil.getTimeStamp();
		// 验证码输入错误次数
		private int fail = 0;
		
		public String getReceiver() {
			return receiver;
		}
		public void setReceiver(String receiver) {
			this.receiver = receiver;
		}
		public String getCaptcha() {
			return captcha;
		}
		public void setCaptcha(String captcha) {
			this.captcha = captcha;
		}
		public long getTimestamp() {
			return timestamp;
		}
		public void setTimestamp(long timestamp) {
			this.timestamp = timestamp;
		}
		public int getFail() {
			return fail;
		}
		public void setFail(int fail) {
			this.fail = fail;
		}
	}
	
}
